package com.xayy.health.ds.controller;

import cn.hutool.core.thread.ThreadUtil;
import cn.kawins.base.result.CheckResult;
import cn.kawins.base.result.ResultBody;
import cn.kawins.base.utils.BeanUtil;
import cn.kawins.base.utils.CollUtil;
import cn.kawins.base.utils.StringUtil;
import cn.kawins.mybatis.util.SnowflakeId;
import com.xayy.health.core.enums.ModelTrainStatusEnum;
import com.xayy.health.core.enums.WebsocketTopicEnum;
import com.xayy.health.ds.model.DsCalculateModelTrain;
import com.xayy.health.ds.model.DsModelTrainRecord;
import com.xayy.health.ds.service.DsCalculateService;
import com.xayy.health.ds.service.DsModelTrainRecordService;
import com.xayy.health.mgt.mapper.SelectTelemetryDataSourceMapper;
import com.xayy.health.mgt.model.CalculateModelTrain;
import com.xayy.health.mgt.model.dto.TelemetryDto;
import com.xayy.health.mgt.model.vo.PredictDataVo;
import com.xayy.health.mgt.model.vo.ResultDataVo;
import com.xayy.health.mgt.service.CalculateService;
import com.xayy.health.mgt.service.ModelTrainRecordService;
import com.xayy.health.mgt.service.TaskInfoService;
import com.xtck.ha.common.core.web.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping(value = "/health-mgr-back/v1.0/calculate")
@Api(tags = "趋势预测")
@Slf4j
public class DsCalculateController extends BaseController {

    @Autowired
    private DsModelTrainRecordService dsModelTrainRecordService;
    @Autowired
    private DsCalculateService dsCalculateService;
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;


    /**
     * 模型训练
     *
     * @param modelTrain 训练入参
     * @param request    请求
     * @return ResultBody
     */
    @ApiOperation(value = "模型训练")
    @PostMapping("train")
    public ResultBody train(@RequestBody DsCalculateModelTrain modelTrain, HttpServletRequest request) {
        // 判断旧模型名称重复
        if (StringUtil.isNotEmpty(modelTrain.getModelName())) {
            CheckResult<Object> checkModelName = dsModelTrainRecordService.checkModelName(modelTrain);
            if (checkModelName.no()) {
                return CheckResult.fail(checkModelName.getCheckMsg()).body();
            }
        }
        List<String> paramCodes = CollUtil.newArrayList();
        paramCodes.add(modelTrain.getParamCode());
        modelTrain.setParamCodes(paramCodes);
        Long recordId = new SnowflakeId().genId("tb_model_train_record", "id");
        DsModelTrainRecord modelTrainRecord = BeanUtil.copyBean(modelTrain, DsModelTrainRecord.class);
        modelTrainRecord.setId(recordId.toString());
        modelTrainRecord.setCreateTime(new Date());
        modelTrainRecord.setStatus(ModelTrainStatusEnum.RUNNING.getCode());
        if (StringUtil.isEmpty(modelTrain.getOldModelName()))
            dsModelTrainRecordService.insertT(modelTrainRecord);

        //模型训练修改为异步调用
        asyncCalculateModelTrial(modelTrain, recordId, request);
        return ResultBody.success();
    }

    /**
     * 异步调用试算
     *
     * @param modelTrain 训练入参
     * @param recordId 记录id
     */
    public void asyncCalculateModelTrial(DsCalculateModelTrain modelTrain, Long recordId, HttpServletRequest request) {
        ThreadUtil.execute(() -> {
            String userid = request.getHeader("Userid");
            try {
                ResultBody result = dsCalculateService.modelTrial(modelTrain, recordId).body();
                simpMessagingTemplate.convertAndSend(WebsocketTopicEnum.CALCULATE.getCode() + "/" + userid, result);
            } catch (Exception e) {
                simpMessagingTemplate.convertAndSend(WebsocketTopicEnum.CALCULATE.getCode() + "/" + userid, ResultBody.failed(118, e.getMessage()));
            }
        });
    }

    /**
     * 调用模型
     * @param modelTrain 训练入参
     * @param request 请求入参
     * @return ResultBody
     */
    @ApiOperation(value = "调用模型")
    @PostMapping("startModel")
    public ResultBody startModel(@RequestBody DsCalculateModelTrain modelTrain, HttpServletRequest request) {
        List<String> paramCodes = CollUtil.newArrayList();
        paramCodes.add(modelTrain.getParamCode());
        modelTrain.setParamCodes(paramCodes);
        modelTrain.setSatelliteMid("");
        String userid = request.getHeader("Userid");
        asyncCalcute(modelTrain, userid);
        return ResultBody.success();
    }

    public void asyncCalcute(DsCalculateModelTrain modelTrain, String userId) {
        ThreadUtil.execute(() -> {
            try {
                ResultBody result = dsCalculateService.startModel(modelTrain).body();
                log.info("趋势预测手动试算=======user={}",WebsocketTopicEnum.CALCULATE_TRY.getCode() + "/" + userId);
                simpMessagingTemplate.convertAndSend(WebsocketTopicEnum.CALCULATE_TRY.getCode() + "/" + userId, result);
            } catch (Exception e) {
                log.error("趋势预测手动试算=======user={}",WebsocketTopicEnum.CALCULATE_TRY.getCode() + "/" + userId,e);
                simpMessagingTemplate.convertAndSend(WebsocketTopicEnum.CALCULATE_TRY.getCode() + "/" + userId, ResultBody.failed(e.getMessage()));
            }
        });

    }

    /**
     * 上线运行
     * @param telemetryDto 入参
     * @return ResultBody
     */
    @ApiOperation(value = "上线运行")
    @PostMapping("online")
    public ResultBody online(@Validated @ApiParam("入参") @RequestBody TelemetryDto telemetryDto) {
        return dsCalculateService.online(telemetryDto).body();
    }


    /**
     * 获取任务预测点集合
     * @param predictDataVo 预测入参
     * @return ResultBody
     */
    @ApiOperation(value = "获取任务预测点集合")
    @PostMapping("getTaskTrendDataList")
    public ResultBody getTaskTrendDataList(@Valid @RequestBody PredictDataVo predictDataVo) throws UnknownHostException {
        return ResultBody.success(dsCalculateService.getTaskTrendDataList(predictDataVo));
    }

    /**
     * 根据时间段获取预测结果数据
     * @param resultDataVo 预测入参
     * @return ResultBody
     */
    @ApiOperation(value = "获取预测结果数据")
    @PostMapping("getResultDataList")
    public ResultBody getResultDataList(@Valid @RequestBody ResultDataVo resultDataVo) throws UnknownHostException {
        return ResultBody.success(dsCalculateService.getResultDataList(resultDataVo));
    }


    /**
     * 删除模型任务
     * @param modelTypeId 模型任务id
     * @return ResultBody
     */
    @ApiOperation(value = "删除模型任务")
    @GetMapping("deleteModelTaskById/{modelTypeId}")
    public ResultBody deleteModelTaskById(@PathVariable(value = "modelTypeId") @ApiParam("模型任务id") Long modelTypeId) {
        return ResultBody.success(dsModelTrainRecordService.deleteModelTaskById(modelTypeId));
    }
}
